package com.knowif.backend.service;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import com.knowif.backend.config.WxPayProperties;
import com.knowif.backend.dto.FastAskOrderDto;
import com.knowif.backend.util.CertSSLUtil;
import com.knowif.backend.util.IPUtil;
import com.knowif.dao.TUserMapper;
import com.knowif.enumInfo.UserOrderStatusEnum;
import com.knowif.pojo.*;
import com.knowif.search.SearchCondition;
import com.knowif.service.FastAskOrder_service;
import com.knowif.service.UserPayOrder_service;
import com.knowif.service.UserWechat_service;
import com.knowif.system.model.RestBean;
import com.knowif.util.ExampleUtil;
import com.knowif.util.WechatMiniUtil;
import com.knowif.util.commonUtil.SecurityUtil;
import com.knowif.util.commonUtil.StringUtil;
import com.knowif.util.paramUtil.DateFormatUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.*;

/**
 * @author ：Xh
 * @date ：Created in 2019/9/8 0008 22:52
 */
@Service
@Slf4j
public class FastAskOrderService {

    @Autowired
    private FastAskOrder_service fastAskOrder_service;
    @Autowired
    private WxPayProperties wxPayProperties;
    @Autowired
    private WxPayService wxPayService;
    @Resource
    private RedisTemplate<String, FastAskOrder> redisTemplate;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserPayOrder_service userPayOrder_service;
    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private WechatMiniUtil wechatMiniUtil;
    @Autowired
    private UserWechat_service userWechat_service;
    @Value("${tencent.pay.cert}")
    private String cert;
    @Value("${tencent.pay.key}")
    private String certKey;

    /**
     * @param fastAskOrder 快问订单
     * @return
     * @author: xh
     * @Description: 添加快问订单
     */
    public FastAskOrder insert(FastAskOrder fastAskOrder) {
        if (fastAskOrder != null) {
            fastAskOrder.setCreateTime(new Date());
            fastAskOrder.setStatus(0);
        }
        fastAskOrder_service.saveFastAskOrder(fastAskOrder);
        return fastAskOrder;
    }

    /**
     * @param fastAskOrder 快问订单
     * @return
     * @author: xh
     * @Description: 更新快问订单
     */
    public RestBean update(FastAskOrder fastAskOrder) {
        int i = fastAskOrder_service.updateFastAskOrderNotNull(fastAskOrder);
        if (i > 0) {
            return RestBean.buildSuccess(fastAskOrder);
        } else {
            return RestBean.buildError("更新失败");
        }
    }

    /**
     * 条件查询快问订单
     *
     * @param example
     * @return
     */
    public List<FastAskOrder> query(FastAskOrderExample example) {
        return fastAskOrder_service.selectFastAskOrder(example);
    }

    public RestBean queryOrderDetail(SearchCondition searchCondition) throws Exception {
        if (searchCondition == null) {
            return RestBean.buildError("请输入要查找订单信息");
        }
        FastAskOrderExample example = ExampleUtil.buildExample(new FastAskOrderExample(), searchCondition);
        return RestBean.build(RestBean.success_code, "", fastAskOrder_service.selectFastAskOrder(example));
    }

    /**
     * 快问订单生成预支付信息
     *
     * @param fastAskOrderDto
     * @param request
     * @return
     */
    public RestBean prepay(FastAskOrderDto fastAskOrderDto, HttpServletRequest request) {
        if(fastAskOrderDto == null){
            return RestBean.buildError("请输入订单信息");
        }
        FastAskOrder fastAskOrder = insert(fastAskOrderDto.getFastAskOrder());
        String out_trade_no = ("" + System.currentTimeMillis() + StringUtil.getRandom(5)).toUpperCase();
        String nonceStr = StringUtil.getRandom(10);
        if (fastAskOrder == null) {
            return RestBean.buildError("没有此订单", RestBean.not_authorized);
        }
        if (fastAskOrder.getStatus() > 0) {//判断该订单是否为未支付状态
            return RestBean.build(RestBean.not_authorized, "该订单已过期");
        }
        String ip = IPUtil.getIpAddress(request);

        int pricefee = new Double(fastAskOrder.getPrice().doubleValue() * 100).intValue();
        if (pricefee <= 0) {
            return RestBean.buildError("订单金额设置错误");
        }

        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();

        orderRequest.setOpenid(fastAskOrderDto.getOpenid());
        orderRequest.setBody("快问订单支付");
        orderRequest.setMchId(wxPayProperties.getMchId());
        orderRequest.setAppid(wxPayProperties.getAppId());
        orderRequest.setTradeType("JSAPI");
        orderRequest.setOutTradeNo(out_trade_no);
        orderRequest.setNonceStr(nonceStr);
        orderRequest.setTotalFee(pricefee);
        orderRequest.setSpbillCreateIp(ip);
        orderRequest.setNotifyUrl("https://www.zhishiya.online/wechat/fastAskOrder/notify.do");

        try {
            Object order = wxPayService.createOrder(orderRequest);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(order));
            JSONObject json = new JSONObject();
            SortedMap<String, Object> data = new TreeMap<>();
            String timeStamp = System.currentTimeMillis() + "";
            timeStamp = timeStamp.substring(0, 10);

            //注：第二次生成sign
            String random = StringUtil.getRandom(10);
            data.put("appId", wxPayProperties.getAppId());
            data.put("nonceStr", random);
            data.put("package", jsonObject.getString("packageValue"));
            data.put("signType", "MD5");
            data.put("timeStamp", timeStamp);
            json.put("sign", SecurityUtil.stringToMD5(StringUtil.getMiniSign(data).append("key=" + wxPayProperties.getMchKey()).toString()).toUpperCase());
            json.put("package", jsonObject.getString("packageValue"));
            json.put("nonceStr", random);
            json.put("timeStamp", timeStamp);
            json.put("fastAskOrder", fastAskOrder);

            //放入redis
            redisTemplate.opsForValue().set(out_trade_no, fastAskOrder);

            return RestBean.buildSuccess(json);
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return RestBean.buildError("wechat pay system error");
    }

    /**
     * 支付成功回调
     *
     * @param notifyResult
     */
    public void handleNotify(WxPayOrderNotifyResult notifyResult) {
        String outTradeNo = notifyResult.getOutTradeNo();
        UserOrderFlow userOrderFlow = userPayOrder_service.selectUserOrderFlowByWechatTradeNo(outTradeNo);
        //再次防止伪支付回调
        if (redisTemplate.hasKey(outTradeNo) && userOrderFlow == null) {
            try {
                //检查查询以及返回结果，失败均会抛出异常
                notifyResult.checkResult(wxPayService, "MD5", true);
                FastAskOrder fastAskOrder = redisTemplate.opsForValue().get(outTradeNo);
                log.info("微信支付回调" + JSONObject.toJSONString(fastAskOrder));
                //1为已支付未回答 更新订单信息
                fastAskOrder.setStatus(1);
                fastAskOrder_service.updateFastAskOrder(fastAskOrder);

                Double price = new BigDecimal(notifyResult.getTotalFee()).divide(new BigDecimal("100")).doubleValue();

                //插入流水
                UserOrderFlow orderFlow = new UserOrderFlow();
                orderFlow.setOperation("支付成功");
                orderFlow.setStatus(UserOrderStatusEnum.PAID.getState());
                orderFlow.setIsSuccess(1);
                orderFlow.setWechatTradeNo(outTradeNo);
                orderFlow.setPayMoney(price);
                //1表示是快问订单
                orderFlow.setPayType(1);
                orderFlow.setCreateTime(new Date());
                orderFlow.setUserOrderId(fastAskOrder.getId());
                userPayOrder_service.insertUserOrderFlow(orderFlow);

                //发送微信通知
                TUser tutor = tUserMapper.selectByPrimaryKey(fastAskOrder.getTutorId());
                UserWechat userWechat = userWechat_service.selectByMiniOpenid(tutor.getOpenid());//导师
                UserWechat userWechatToUser = userWechat_service.selectByMiniOpenid(notifyResult.getOpenid());//学员

                TUser user = tUserMapper.selectUserByOpenid(notifyResult.getOpenid());//学员

                String accessToken = stringRedisTemplate.opsForValue().get("wechatAccessToken");
                if (userWechat != null && user != null) {
                    //  x-nMYhknvGkJq256WczOxg1cih9wm2LZMp9nnDS6CMg (新订单通知 导师)
                    //  yA6imDOE8YBiZJGq417cHz8OPfm97u8OWf0JNSGoDZ8 (购买成功通知 学员)
                    List<Map<String, String>> list = new LinkedList<>();
                    Map<String, String> map1 = new HashMap<>();
                    map1.put("value", user.getFullName());
                    list.add(map1);
                    map1 = new HashMap<>();

                    map1.put("value", fastAskOrder.getQuestion());
                    list.add(map1);
                    map1 = new HashMap<>();
                    map1.put("value", price + "");
                    list.add(map1);
                    map1 = new HashMap<>();
                    map1.put("value", "已支付");
                    list.add(map1);
                    map1 = new HashMap<>();
                    map1.put("value", DateFormatUtil.dateToString(new Date()));
                    list.add(map1);
                    //通知导师
                    wechatMiniUtil.sendFATemplate(accessToken, "导师您好，您有一个新的快问订单！", userWechat.getPlatform(), list, "如在48小时未处理订单，系统将自动取消该订单。立即进入订单详情！",
                            "/myPages/Reply/Reply?fastOrderOrderId=" + fastAskOrder.getId(), "x-nMYhknvGkJq256WczOxg1cih9wm2LZMp9nnDS6CMg");

                    list = new LinkedList<>();
                    map1 = new HashMap<>();
                    map1.put("value", price + "");
                    list.add(map1);
                    map1 = new HashMap<>();
                    map1.put("value", fastAskOrder.getQuestion());
                    list.add(map1);
                    map1 = new HashMap<>();
                    map1.put("value", SecurityUtil.stringToMD5(fastAskOrder.getId() + ""));
                    list.add(map1);
                    //通知学员
                    wechatMiniUtil.sendFATemplate(accessToken, "您的订单已支付成功！", userWechatToUser.getPlatform(), list, "导师将在48小时内处理快问订单，请耐心等待～",
                            "/myPages/Replylists/Replylists", "yA6imDOE8YBiZJGq417cHz8OPfm97u8OWf0JNSGoDZ8");
                } else {
                    log.info("UserWechat 为空================================================>  " + tutor.getOpenid());
                }
                redisTemplate.delete(outTradeNo);
            } catch (WxPayException e) {
                throw new RuntimeException("微信支付签名不一致");
            }
        } else {
            throw new RuntimeException("订单不存在");
        }
    }

    /**
     * 超时退款
     *
     * @param fastAskOrder
     */
    public void refund(FastAskOrder fastAskOrder) {

//        String nonceStr = StringUtil.getRandom(32);
//        //退款订单号
//        String out_refund_no = "" + System.currentTimeMillis() + StringUtil.getRandom(5);//必须存起来
//
//
//        UserOrderFlow orderFlow = userPayOrder_service.selectUserOrderFlowByFastAskOrderId(fastAskOrder.getId());
//        if (orderFlow == null) {
//            log.error("{}", "退款订单不存在");int totalFee = new Double(fastAskOrder.getPrice().doubleValue() * 100).intValue();
//            return;
//        }
//
//        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
//        refundRequest.setAppid(wxPayProperties.getAppId());
//        refundRequest.setMchId(wxPayProperties.getMchId());
//        refundRequest.setNonceStr(nonceStr);
//        refundRequest.setOutTradeNo(orderFlow.getWechatTradeNo());
//        refundRequest.setOutRefundNo(out_refund_no);
//        refundRequest.setTotalFee(totalFee);
//        refundRequest.setRefundFee(totalFee);
//        refundRequest.setNotifyUrl("https://www.zhishiya.online/wechat/fastAskOrder/refundNotify.do");
//        refundRequest.setRefundDesc("订单超时，全额退款");
//
//
//        SortedMap<String, Object> params = new TreeMap<String, Object>();
//
//        params.put("appid", wxPayProperties.getAppId());
//        params.put("mch_id", wxPayProperties.getMchId());
//        params.put("nonce_str", nonceStr);
//        params.put("out_trade_no", orderFlow.getWechatTradeNo());
//        params.put("out_refund_no", out_refund_no);//退款单号
//
//        params.put("total_fee", totalFee);
//        params.put("refund_fee", totalFee);
//        params.put("notify_url", "https://www.zhishiya.online/wechat/fastAskOrder/refundNotify.do");
//        log.info("快问订单退款total_fee ===========================>" + totalFee);
//        params.put("refund_desc", "订单超时，全额退款");//退款原因
//        String[] ignoredParams = {};
//        String sign = SignUtils.createSign(params, "MD5", wxPayProperties.getMchKey(), ignoredParams);
//        params.put("sign", sign);
//
//        refundRequest.setSign(sign);
//
//        try {
//            wxPayService.refund(refundRequest);
//        } catch (WxPayException e) {
//            log.error("退款失败:{}", e.getMessage());
//            e.printStackTrace();
//        }

        UserOrderFlow orderFlow = userPayOrder_service.selectUserOrderFlowByFastAskOrderId(fastAskOrder.getId());
        if (orderFlow == null) {
            log.error("{}", "退款订单不存在");
            return;
        }
        int totalFee = new Double(fastAskOrder.getPrice().doubleValue() * 100).intValue();
        SortedMap<String, Object> params = new TreeMap<String, Object>();
        String out_refund_no = ""+System.currentTimeMillis()+StringUtil.getRandom(5);//必须存起来
        params.put("appid",wxPayProperties.getAppId());
        params.put("mch_id",wxPayProperties.getMchId());
        params.put("nonce_str",StringUtil.getRandom(32));
        params.put("out_trade_no",orderFlow.getWechatTradeNo());
        params.put("out_refund_no",out_refund_no);//退款单号
        params.put("total_fee",totalFee);//
        params.put("refund_fee",totalFee);
        params.put("notify_url","https://www.zhishiya.online/wechat/fastAskOrder/refundNotify.do");
        params.put("refund_desc","订单超时，全额退款");//退款原因
        String sign = StringUtil.getMiniSign(params).append("key=" + wxPayProperties.getMchKey()).toString();//key必须加一个
        params.put("sign", SecurityUtil.stringToMD5(sign).toUpperCase());
        String xml = StringUtil.toMiniWechatPayXml(params);
        System.out.println(xml);
        try {
            URL url = new URL("https://api.mch.weixin.qq.com/secapi/pay/refund");
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            con.setRequestMethod("POST");
            con.setUseCaches(false);
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setSSLSocketFactory(new CertSSLUtil().getSocketFactoryPEM(cert,certKey));

            con.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
            OutputStream out = con.getOutputStream();
            out.write(xml.getBytes());
            out.flush();
            out.close();
            InputStream in = null;
            if (con.getResponseCode() == 200) {
                in = con.getInputStream();
            } else {
                in = con.getErrorStream();
                String temp = "";
                String result = "";
                BufferedReader br = new BufferedReader(new InputStreamReader(in));
                while ((temp = br.readLine()) != null) {
                    result += temp;
                }
                System.out.println(result);
            }

            String temp = "";
            String result = "";
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            while ((temp = br.readLine()) != null) {
                result += temp;
            }
            System.out.println(result);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 超时退款回调
     *
     * @param refundNotify
     */
    public void handleRefundNotify(WxPayRefundNotifyResult refundNotify) {
        //再次防止伪退款回调
        if ("SUCCESS".equals(refundNotify.getReturnCode())) {
            try {
                WxPayRefundNotifyResult.ReqInfo reqInfo = refundNotify.getReqInfo();
                String outTradeNo = reqInfo.getOutTradeNo();
                UserOrderFlow orderFlow = userPayOrder_service.selectUserOrderFlowByWechatTradeNo(outTradeNo);
                if(orderFlow == null){
                    throw new RuntimeException("退款订单不存在");
                }
                //快问订单ID
                Integer fastAskOrderId = orderFlow.getUserOrderId();
                FastAskOrder fastAskOrder = fastAskOrder_service.selectFastAskOrderById(fastAskOrderId);
                if(fastAskOrder == null){
                    throw new RuntimeException("退款订单不存在");
                }

                int price = reqInfo.getRefundFee();
                Double ps = price * 1.0 / 100;
                orderFlow.setStatus(UserOrderStatusEnum.REFUND.getState());//订单退款
                orderFlow.setOperation("已退款,金额为：" + ps + "元");
                userPayOrder_service.updateFastAskOrderFlow(orderFlow);//更新退款订单流水

                //状态改为已退款,更新
                fastAskOrder.setStatus(3);
                fastAskOrder_service.updateFastAskOrder(fastAskOrder);
            }catch (Exception e) {
                e.printStackTrace();
                log.info("{}", e.getMessage());
                throw new RuntimeException("解析参数失败");
            }
        } else {
            throw new RuntimeException("退款失败");
        }
    }

    public RestBean queryOrderById(int fastAskOrderId) {
        return RestBean.buildSuccess(fastAskOrder_service.selectFastAskOrderById(fastAskOrderId));
    }
}
